﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Reactor.Client.Messages;
using Reactor.Client.Services;
using Reactor.Client.Web.Data;

namespace Reactor.Client.ViewModel
{
    public class ServiceViewModel : ServiceBaseViewModel
    {
        private readonly IMessenger _messenger;
        private readonly IDialogService _dialogService;
        private readonly IReactorServiceAgent _serviceAgent;

        #region Fields

        private Service _service;
        private object _playButtonImage;
        private object _stopButtonImage;

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceViewModel"/> class.
        /// </summary>
        /// <param name="messenger">The messenger.</param>
        /// <param name="dialogService">The dialog service.</param>
        /// <param name="serviceAgent">The service agent.</param>
        /// <param name="service">The service.</param>
        public ServiceViewModel(IMessenger messenger, IDialogService dialogService, IReactorServiceAgent serviceAgent, Service service) : base(serviceAgent)
        {
            if (messenger == null) throw new ArgumentNullException("messenger");
            if (dialogService == null) throw new ArgumentNullException("dialogService");
            if (serviceAgent == null) throw new ArgumentNullException("serviceAgent");
            if (service == null) throw new ArgumentNullException("service");

            _messenger = messenger;
            _dialogService = dialogService;
            _serviceAgent = serviceAgent;

            ServicePackages = new ObservableCollection<ServicePackageViewModel>();

            LoadService(service);

            PropertyChanged += (s,e) =>
                                   {
                                       if (e.PropertyName != "IsOnline") return;

                                       UpdateControlButtons();
                                       UpdateStatusImage();
                                   };

            DetermineOnlineStatus();
            UpdateStatusImage();
        }

        private void UpdateControlButtons()
        {
            if (IsOnline)
            {
                PlayButtonImage = new BitmapImage(new Uri(Application.Current.Host.Source, "../Images/control_play_blue.png"));
                StopButtonImage = new BitmapImage(new Uri(Application.Current.Host.Source, "../Images/control_stop.png"));
            }
            else
            {
                PlayButtonImage = new BitmapImage(new Uri(Application.Current.Host.Source, "../Images/control_play.png"));
                StopButtonImage = new BitmapImage(new Uri(Application.Current.Host.Source, "../Images/control_stop_blue.png"));
            }
        }

        public object StopButtonImage
        {
            get { return _stopButtonImage; }
            set
            {
                if (value == _stopButtonImage) return;

                _stopButtonImage = value;
                RaisePropertyChanged("StopButtonImage");
            }
        }

        public object PlayButtonImage
        {
            get { return _playButtonImage; }
            set
            {
                if (value == _playButtonImage) return;

                _playButtonImage = value;
                RaisePropertyChanged("PlayButtonImage");
            }
        }

        public ICommand TransferCommand
        {
            get { return new RelayCommand(HandleTransferCommand); }
        }

        public ICommand OrphanCommand
        {
            get { return new RelayCommand(HandleOrphanCommand); }
        }

        public ICommand UpgradeCommand
        {
            get { return new RelayCommand(HandleUpgradeCommand); }
        }

        public ObservableCollection<ServicePackageViewModel> ServicePackages { get; private set; }

        public void LoadService(Service service)
        {
            if (service == null) throw new ArgumentNullException("service");

            _service = service;

            Name = service.Name;
            Version = service.Version;
            VersionDisplay = string.Format("v{0}", service.Version);

            _serviceAgent.GetAllServicePackages(LoadServicePackages);
        }

        protected override void DetermineOnlineStatus()
        {
            var interval = TimeSpan.FromMinutes(1);
            if (HealthCheckInterval.HasValue)
                interval = HealthCheckInterval.Value;

            var pastInterval = (DateTime.Now - _service.LastSeen) > interval;
            IsOnline = !pastInterval;
        }

        private void LoadServicePackages(IEnumerable<ServicePackageViewModel> servicePackages)
        {
            var packagesForCurrentService = servicePackages.Where(s => s.Name == Name);

            if (!packagesForCurrentService.Any()) return;

            var currentVersion = new Version(Version);
            foreach (var servicePackageViewModel in packagesForCurrentService)
            {
                var version = new Version(servicePackageViewModel.Version);

                if (version > currentVersion)
                    ServicePackages.Add(servicePackageViewModel);
            }
        }

        private void HandleTransferCommand()
        {
            SendSelectedEvent();

            _dialogService.ShowTransferServiceDialog();
        }

        private void HandleOrphanCommand()
        {
            SendSelectedEvent();

            _dialogService.ShowOrphanServiceDialog();
        }

        private void HandleUpgradeCommand()
        {
            SendSelectedEvent();

            _dialogService.ShowUpgradeServiceDialog();
        }

        private void SendSelectedEvent()
        {
            _messenger.Send(new ServiceSelectedEvent {SelectedService = this});
        }
    }
}
